package com.jzo2o.foundations.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.foundations.constants.RedisConstants;
import com.jzo2o.foundations.enums.FoundationStatusEnum;
import com.jzo2o.foundations.mapper.RegionMapper;
import com.jzo2o.foundations.mapper.ServeMapper;
import com.jzo2o.foundations.mapper.ServeTypeMapper;
import com.jzo2o.foundations.model.domain.Region;
import com.jzo2o.foundations.model.domain.Serve;
import com.jzo2o.foundations.model.domain.ServeItem;
import com.jzo2o.foundations.model.dto.response.ServeAggregationSimpleResDTO;
import com.jzo2o.foundations.model.dto.response.ServeAggregationTypeSimpleResDTO;
import com.jzo2o.foundations.model.dto.response.ServeCategoryResDTO;
import com.jzo2o.foundations.model.dto.response.ServeSimpleResDTO;
import com.jzo2o.foundations.service.HomeService;
import com.jzo2o.foundations.service.IRegionService;
import com.jzo2o.foundations.service.IServeItemService;
import com.jzo2o.foundations.service.IServeService;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 用户端 - 门户查询接口实现类
 */
@Service
@Slf4j
public class HomeServiceImpl implements HomeService {

    @Resource
    private ServeMapper serveMapper; // 服务Mapper
    @Resource
    private IRegionService regionService; // 区域Service
    @Resource
    private ServeTypeMapper serveTypeMapper; // 服务类型Mapper
    @Resource
    private IServeService serveService; // 服务Service
    @Resource
    private IServeItemService serveItemService; // 服务项Service
    @Resource
    private HomeService homeService; // 本类


    /**
     * 根据区域id查询已开通的服务类型
     * 获取首页服务类型及服务项
     *
     * @param regionId 区域id
     * @return 已开通的服务类型
     */
    @Caching(cacheable = {
            //result为null时,属于缓存穿透情况，缓存时间30分钟
            @Cacheable(value = RedisConstants.CacheName.SERVE_ICON, key = "#regionId", unless = "#result.size() != 0", cacheManager = RedisConstants.CacheManager.THIRTY_MINUTES),
            //result不为null时,永久缓存
            @Cacheable(value = RedisConstants.CacheName.SERVE_ICON, key = "#regionId", unless = "#result.size() == 0", cacheManager = RedisConstants.CacheManager.FOREVER)
    })
    @Override
    public List<ServeCategoryResDTO> queryServeIconCategoryByRegionIdCache(Long regionId) {
        //1、检验当前城市是否为启用状态
        Region region = regionService.getById(regionId);
        if (ObjectUtil.isEmpty(region) || ObjectUtil.equal(FoundationStatusEnum.DISABLE.getStatus(), region.getActiveStatus())) {
            return Collections.emptyList();
        }

        //2、根据城市编码查询所有已上架的服务类型及其下属的服务项图标
        List<ServeCategoryResDTO> list = serveMapper.findServeIconCategoryByRegionId(regionId);
        if (ObjectUtil.isEmpty(list)) {
            return Collections.emptyList();
        }

        //3、按要求：服务类型取前两个，每个类型下服务项取前4个
        //list的截止下标，subList是用来截取列表，返回一个子列表。截取范围是 [0, endIndex)。
        int endIndex = Math.min(list.size(), 2);
        List<ServeCategoryResDTO> serveCategoryResDTOS = new ArrayList<>(list.subList(0, endIndex));
        //遍历刚截取的子列表，获取每个服务类型下的服务项
        serveCategoryResDTOS.forEach(v -> {
            List<ServeSimpleResDTO> serveResDTOList = v.getServeResDTOList(); //服务项列表
            //serveResDTOList的截止下标
            int endIndex2 = Math.min(serveResDTOList.size(), 4);
            List<ServeSimpleResDTO> serveSimpleResDTOS = new ArrayList<>(serveResDTOList.subList(0, endIndex2));
            v.setServeResDTOList(serveSimpleResDTOS);
        });

        return serveCategoryResDTOS;
    }


    /**
     * 用户端 - 首页全部服务：服务类型列表查询
     * 查询所有存在已上架服务的服务类型
     * 根据区域id查询简略服务类型列表
     */
    @Caching(cacheable = {
            //result为null时,属于缓存穿透情况，缓存时间30分钟
            @Cacheable(value = RedisConstants.CacheName.SERVE_TYPE, key = "#regionId", unless = "#result.size() != 0", cacheManager = RedisConstants.CacheManager.THIRTY_MINUTES),
            //result不为null时,永久缓存
            @Cacheable(value = RedisConstants.CacheName.SERVE_TYPE, key = "#regionId", unless = "#result.size() == 0", cacheManager = RedisConstants.CacheManager.FOREVER)
    })
    @Override
    public List<ServeAggregationTypeSimpleResDTO> getServeTypeList(Long regionId) {
        //1、检验当前城市是否为启用状态
        Region region = regionService.getById(regionId);
        if (ObjectUtil.isEmpty(region) || ObjectUtil.equal(FoundationStatusEnum.DISABLE.getStatus(), region.getActiveStatus())) {
            return Collections.emptyList();
        }
        //2、根据区域id查询服务类型列表
        List<ServeAggregationTypeSimpleResDTO> serveTypeList = serveTypeMapper.getServeTypeListByRegionId(regionId);
        if (CollUtils.isEmpty(serveTypeList)) {
            return Collections.emptyList();
        }

        return serveTypeList;
    }


    /**
     * 用户端 - 获取首页热门服务
     *
     * @param regionId 区域id
     * @return 热门服务列表
     */
    @Caching(cacheable = {
            //result为null时,属于缓存穿透情况，缓存时间30分钟
            @Cacheable(value = RedisConstants.CacheName.HOT_SERVE, key = "#regionId", unless = "#result.size() != 0", cacheManager = RedisConstants.CacheManager.THIRTY_MINUTES),
            //result不为null时,永久缓存
            @Cacheable(value = RedisConstants.CacheName.HOT_SERVE, key = "#regionId", unless = "#result.size() == 0", cacheManager = RedisConstants.CacheManager.FOREVER)
    })
    @Override
    public List<ServeAggregationSimpleResDTO> queryHotServeListByRegionIdCache(Long regionId) {
        //1、检验当前城市是否为启用状态
        Region region = regionService.getById(regionId);
        if (ObjectUtil.isEmpty(region) || ObjectUtil.equal(FoundationStatusEnum.DISABLE.getStatus(), region.getActiveStatus())) {
            return Collections.emptyList();
        }
        //2、根据区域id查询热门且已上架的服务列表
        List<ServeAggregationSimpleResDTO> list = serveMapper.queryHotServeListByRegionId(regionId);
        if (ObjectUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list;
    }

    /**
     * 用户端 - 获取服务详情
     *
     * @param id 服务id
     * @return 服务详情
     */
    @Override
    public ServeAggregationSimpleResDTO queryServeDetail(Long id) {
        //1、检验服务是否存在
        Serve serve = serveService.selectByIdCache(id);
        if (ObjectUtils.isEmpty(serve)) {
            return new ServeAggregationSimpleResDTO();
        }
        //2、检验服务项是否存在
        ServeItem serveItem = serveItemService.selectByIdCache(serve.getServeItemId());
        if (ObjectUtils.isEmpty(serveItem)) {
            return new ServeAggregationSimpleResDTO();
        }
        //封装服务详情
        return ServeAggregationSimpleResDTO.builder()
                .id(serve.getId())
                .serveItemId(serveItem.getId())
                .serveItemName(serveItem.getName())
                .serveItemImg(serveItem.getImg())
                .detailImg(serveItem.getDetailImg())
                .unit(serveItem.getUnit())
                .price(serve.getPrice())
                .cityCode(serve.getCityCode())
                .build();
    }


    /**
     * 刷新区域id相关缓存：首页图标、热门服务、服务分类
     *
     * @param regionId 区域id
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = RedisConstants.CacheName.SERVE_ICON, key = "#regionId", beforeInvocation = true),
            @CacheEvict(value = RedisConstants.CacheName.HOT_SERVE, key = "#regionId", beforeInvocation = true),
            @CacheEvict(value = RedisConstants.CacheName.SERVE_TYPE, key = "#regionId", beforeInvocation = true)
    })
    public void refreshRegionRelateCaches(Long regionId) {
        //刷新缓存：首页图标、热门服务、服务类型
        // 更新每个区域对应的首页服务列表
        homeService.queryServeIconCategoryByRegionIdCache(regionId);
        // 更新每个区域对应的服务类型列表
        homeService.getServeTypeList(regionId);
        // 更新每个区域对应的热门服务列表
        homeService.queryHotServeListByRegionIdCache(regionId);
    }


    /**
     * 根据id查询区域服务信息
     *
     * @param id 服务id
     * @return 服务
     */
    @Override
    @Cacheable(value = RedisConstants.CacheName.SERVE, key = "#id", cacheManager = RedisConstants.CacheManager.ONE_DAY)
    public Serve queryServeByIdCache(Long id) {
        return serveService.getById(id);
    }

    /**
     * 根据id查询服务项
     *
     * @param id 服务项id
     * @return 服务项
     */
    @Override
    @Cacheable(value = RedisConstants.CacheName.SERVE_ITEM, key = "#id", cacheManager = RedisConstants.CacheManager.ONE_DAY)
    public ServeItem queryServeItemByIdCache(Long id) {
        return serveItemService.getById(id);
    }
}
